package model;

import java.util.Arrays;

import model.exception.MacAddressException;


/**
 * MAC Address
 * 
 * @author Dumella De Rosa Gennaro
 */
public class MacAddress  {

	private byte[] macAddress = new byte [6];
	
	/* Costruttori */
	public MacAddress(byte[] mac) throws MacAddressException {
	    if (mac.length == 6) {
	        this.macAddress = mac;
	    } else throw new MacAddressException("Invalid mac address");	
	}
	
	public MacAddress(MacAddress mac) {
		setAddress(mac);
	}
	
	public MacAddress(String mac) throws MacAddressException {
		setMacAddress(mac);
	}
	
	public MacAddress() {
	    setAddress();
	}
	
	/* Metodi Get e Set */
	public byte[] getAddress() {
		return this.macAddress;
	}
	
	public void setMacAddress(String macStr) throws MacAddressException {		
		String[] hex = macStr.split("(\\:|\\-)");
		if (hex.length != 6) {
			throw new MacAddressException();
		}
		try {
			for (int i = 0; i < 6; i++) {				
				macAddress[i] = (byte) Integer.parseInt(hex[i], 16);
			}
		}
		catch (NumberFormatException e) {
			throw new MacAddressException("Invalid hex digit in MAC address: " + macStr, e);
		}
	}
	
	public void setAddress(MacAddress mac) {
	    if (mac != null) {
	        this.macAddress = mac.macAddress;
        } else {
            setAddress();
        }
	}
	
	public void setAddress() {
	    for (int i = 0; i < this.macAddress.length; ++i) {
	        this.macAddress[i] = 0;
	    }
	}
	
	/* Metodi di Utilità */
	public String toString () {
		return toString(':');
	}

	/**
	 * @param ch è il carattere separato nell'indirizzo MAC
	 * @return se (ch == :) ritorna un indirizzo del tipo 00:00:12:34:DA:A0
	 */
	public String toString(char ch) {
		StringBuffer sb = new StringBuffer( 17 );
		for ( int i=44; i>=0; i-=4 ) {
			int nibble =  ((int)( byte2Long(macAddress) >>> i )) & 0xf;
			char nibbleChar = (char)( nibble > 9 ? nibble + ('A'-10) : nibble + '0' );
			sb.append( nibbleChar );
			if ( (i & 0x7) == 0 && i != 0 ) {
				sb.append( ch );
			}
		}
		return sb.toString();		
	}

	@Override
	public boolean equals(Object arg0) {
		if(arg0 == null)
			return false;
		if (arg0 instanceof MacAddress) {
			MacAddress value = (MacAddress) arg0;
			if(Arrays.equals(value.getAddress(), getAddress()))
				return true;
		}
		return false;
	}
	
	/* Metodi Privati*/
	/**
	 * Restituisce il tipo long dall'array di byte
	 * @param addr
	 */
	private long byte2Long(byte addr[]) {
	    long address = 0;
		if (addr != null) {
		    if (addr.length == 6) {
			address = unsignedByteToLong(addr[5]);
			address |= (unsignedByteToLong(addr[4]) << 8);
			address |= (unsignedByteToLong(addr[3]) << 16);
			address |= (unsignedByteToLong(addr[2]) << 24);
			address |= (unsignedByteToLong(addr[1]) << 32);
			address |= (unsignedByteToLong(addr[0]) << 40);
		    } 
		} 
		return address;
	}	
	
	private long unsignedByteToLong(byte b) {
	    return (long) b & 0xFF;
	}
	
	
	public static void main(String[] args) throws MacAddressException {
		
		MacAddress mac1 = new MacAddress("01:02:03:04:05:06");
		byte[] b = {1,2,3,4,5,6};
		MacAddress mac2 = new MacAddress(b);
		MacAddress mac3 = new MacAddress();
		
		System.out.println(mac1.toString());
		System.out.println(mac2.toString());
		System.out.println(mac3.toString());
		System.out.println(mac2.equals(mac1));
	}
	
}